package com.tanhua.app.service;

import cn.hutool.core.collection.CollUtil;
import com.tanhua.api.CommentApi;
import com.tanhua.api.UserInfoApi;
import com.tanhua.app.exception.BusinessException;
import com.tanhua.app.intercept.UserHolder;
import com.tanhua.commons.utils.Constants;
import com.tanhua.model.enums.CommentType;
import com.tanhua.model.mongo.Comment;
import com.tanhua.model.pojo.UserInfo;
import com.tanhua.model.vo.CommentVo;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.PageResult;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class CommentService {

    @DubboReference
    private CommentApi commentApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 根据动态id查询该动态的评论
     * @param page
     * @param pagesize
     * @param movementId
     * @return
     */
    public PageResult findComments(Integer page, Integer pagesize, String movementId) {
        //1.通过Api接口实现查询
        List<Comment> listComment = commentApi.findComments(page,pagesize, CommentType.COMMENT,movementId);

        //2.判断评论是否存在
        if (CollUtil.isEmpty(listComment)){
            //评论为空看，则直接放回
            return new PageResult(page,pagesize,0, null);
        }

        //3.获取某条动态的评论用户id
        List<Long> ids = listComment.stream().map(Comment::getUserId).collect(Collectors.toList());

        //4.查询评论用户的详情
        List<UserInfo> userInfoList = userInfoApi.findByUserId(ids);

        //5.将评论人的详情装换成map集合
        Map<Long, UserInfo> userInfoMap = userInfoList.stream().collect(Collectors.toMap(UserInfo::getId, Function.identity()));

        //6.封装成CommentVo对象
        List<CommentVo> commentVos = new ArrayList<>();
        for (Comment comment : listComment) {
            //通过评论人的id, 在userInfoMap的集合中找到与自身对象的个人详情
            UserInfo userInfo = userInfoMap.get(comment.getUserId());
            //封装成vo对象
            if (userInfo != null){
                CommentVo commentVo = CommentVo.init(userInfo, comment);
                commentVos.add(commentVo);
            }
        }
        return new PageResult(page,pagesize,0,commentVos);
    }

    /**
     * 发布评论
     * @param movementId
     * @param comment
     */
    public void saveComments(String movementId, String comment) {
        //保存评论数据
        //1.获取操作用户的id
        Long userId = UserHolder.getUserId();
        //2.构造comment对象
        Comment newComment = new Comment();
        newComment.setPublishId(new ObjectId(movementId));  //被评论动态的id
        newComment.setCommentType(CommentType.COMMENT.getType()); //评论类型：是评论
        newComment.setContent(comment); //评论内容
        newComment.setUserId(userId);  //评论动态的人（也就当前登录系统的用户）
        newComment.setCreated(System.currentTimeMillis()); //评论时间
        //3.通过接口存储发布的评论（怎么可以通过一个方法实现所有类型的互动数据保存）
        Integer commentCount = commentApi.save(newComment);
    }

    /**
     * 点赞动态
     * @param movementId
     * @return
     */
    public Integer saveLike(String movementId) {
        //1，判断动态该用户是否点赞过
        Boolean hasComment = commentApi.hasComment(movementId, UserHolder.getUserId(), CommentType.LIKE.getType());

        //2.如果点赞过，则抛出异常
        if (hasComment){
            throw new BusinessException(ErrorResult.likeError());
        }

        //3.若没有，则点赞，并封装点赞数据
        Comment likeComment = new Comment();
        likeComment.setPublishId(new ObjectId(movementId)); //封装动态id:是点赞的哪条动态
        likeComment.setCommentType(CommentType.LIKE.getType()); //封装互动类型：点赞类型
        likeComment.setUserId(UserHolder.getUserId()); //封装用户id: 谁点赞了该动态
        likeComment.setCreated(System.currentTimeMillis()); //封装点赞时间

        //4.调用CommentApi存储点赞数据
        Integer likeCount = commentApi.save(likeComment);

        //5.将点赞数据存储到缓存中
        String key = Constants.FOCUS_USER_KEY + movementId; //该key是指代哪一条动态缓存在redis中
        String hasKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId(); //该key是指代评论该动态的用户id是谁，把谁评论了该动态存入到缓存中
        redisTemplate.opsForHash().put(key, hasKey, "1");

        //6.返回点赞总数
        return likeCount;
    }

    /**
     * 取消点赞
     * @param movementId
     * @return
     */
    public Integer removeLike(String movementId) {
        //1.判断该动态用户是否点过赞
        Boolean hasLike = commentApi.hasComment(movementId, UserHolder.getUserId(), CommentType.LIKE.getType());
        //2.不存在点赞数据，则取消点暂时抛出异常
        if (!hasLike){
            throw new BusinessException(ErrorResult.disLikeError());
        }
        //3.存在，删除点赞数据
        Comment likeComment = new Comment();
        likeComment.setPublishId(new ObjectId(movementId));
        likeComment.setUserId(UserHolder.getUserId());
        likeComment.setCommentType(CommentType.LIKE.getType());

        Integer likeCount = commentApi.remove(likeComment);
        //4.删除点赞缓存
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hasKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().delete(key,hasKey);

        //5，放回点赞总数
        return likeCount;
    }


    /**
     * 喜欢动态
     * @param movementId
     * @return
     */
    public Integer saveLove(String movementId) {
        //1.判断该动态是否被当前用户喜欢
        Boolean aBoolean = commentApi.hasComment(movementId, UserHolder.getUserId(), CommentType.LOVE.getType());
        //2.如果喜欢过，则抛出异常
        if (aBoolean){
            throw new BusinessException(ErrorResult.loveError());
        }
        //3.若没有，则喜欢，并封装点喜欢数据
        Comment loveComment = new Comment();
        loveComment.setPublishId(new ObjectId(movementId)); //封装动态id:是喜欢的哪条动态
        loveComment.setUserId(UserHolder.getUserId());   //封装用户id: 谁喜欢了该动态
        loveComment.setCommentType(CommentType.LOVE.getType());  //封装互动类型：喜欢类型
        loveComment.setCreated(System.currentTimeMillis()); //封装喜欢时间

        //4.调用CommentApi存储喜欢数据
        Integer loveCount = commentApi.save(loveComment);

        //5.将喜欢数据存储到缓存中
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hasKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().put(key,hasKey,"1");

        //6.返回喜欢总数
        return loveCount;
    }

    /**
     * 取消喜欢动态
     * @param movementId
     * @return
     */
    public Integer removeLove(String movementId) {
        //1.查询该用户是否喜欢这条动态
        Boolean aBoolean = commentApi.hasComment(movementId, UserHolder.getUserId(), CommentType.LOVE.getType());

        //2.判断是否喜欢
        if (!aBoolean){
            //没有喜欢，则抛异常
            throw new BusinessException(ErrorResult.disloveError());
        }

        //3.存在喜欢，删除喜欢数据
        Comment loveComment = new Comment();
        loveComment.setPublishId(new ObjectId(movementId));
        loveComment.setUserId(UserHolder.getUserId());
        loveComment.setCommentType(CommentType.LOVE.getType());

        Integer loveCount = commentApi.remove(loveComment);

        //4.删除缓存中的喜欢数据
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hasKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().delete(key,hasKey);

        //5.返回喜欢数
        return loveCount;
    }
}
